package jmetal.util;

import jmetal.core.Problem;
import jmetal.core.Solution;
import jmetal.core.SolutionSet;
import jmetal.qualityIndicator.fastHypervolume.FastHypervolume;

public class HvIndicator {
	private Problem problem;
	
	public HvIndicator(Problem problem){
		this.problem = problem;
	}
	
	/**
	 * calculate HypeValue
	 * @param solutionSet
	 * @return
	 */
	public double getHyperVolume(SolutionSet solutionSet){
		double hvValue = 0.0;
	  	int objNum = solutionSet.get(0).getNumberOfObjectives();
	  	Solution referencePoint = new Solution(solutionSet.get(0).getNumberOfObjectives());	
	  	if(problem.getName().startsWith(ProblemType.DTLZ)){				
			for(int i = 0;i<objNum;i++){
				referencePoint.setObjective(i, 1.1);
			}
	  	}else if(problem.getName().startsWith(ProblemType.WFG)){
			for(int i = 0;i<objNum;i++){
				referencePoint.setObjective(i, 2*(i+1)+1.0);
			}
	  	}
	  	SolutionSet contributionSet = extrateContributionPoint(solutionSet, referencePoint);
	  	if(contributionSet.size()>1){
	  		hvValue = new FastHypervolume().computeHypervolume(contributionSet, referencePoint);
	  	}
	  	return hvValue;
	}
	
	/**
	 * 提取在referencePoint 之内的解
	 * @param solutionSet
	 * @param referencePoint
	 * @return
	 */
	private SolutionSet extrateContributionPoint(SolutionSet solutionSet,
			Solution referencePoint) {
		SolutionSet contributionSolutions = new SolutionSet(solutionSet.size());
		for(int i = 0;i<solutionSet.size();i++){
			Solution solution = solutionSet.get(i);
			boolean flag = true;
			for(int j = 0;j<solution.getNumberOfObjectives();j++){
				if(solution.getObjective(j)>referencePoint.getObjective(j)){
					flag = false;
					break;
				}
			}
			if(flag){
				contributionSolutions.add(solution);
			}
		}
		return contributionSolutions;
	}
}
